package com.aloda.scoring.impl;

import cn.hutool.json.JSONUtil;
import com.aloda.constant.ErrorCode;
import com.aloda.dto.QuestionAndResultListDTO;
import com.aloda.dto.question.QuestionContentDTO;
import com.aloda.entity.App;
import com.aloda.entity.Question;
import com.aloda.entity.ScoringResult;
import com.aloda.entity.UserAnswer;
import com.aloda.exception.BaseException;
import com.aloda.exception.WarnException;
import com.aloda.scoring.DataTreating;
import com.aloda.scoring.ScoringStrategy;
import com.aloda.scoring.anno.ScoringStrategyConfig;
import jakarta.annotation.Resource;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 自定义测评类应用评分策略
 */
@ScoringStrategyConfig(appType = 1, scoringStrategy = 0)
public class CustomTestScoringStrategy implements ScoringStrategy {

    @Resource
    private DataTreating dataTreating;

    /**
     * 执行评分
     *
     * @param choices
     * @param app
     * @return
     * @throws Exception
     */
    @Override
    public UserAnswer doScore(List<String> choices, App app) throws Exception {
        // 1.获取题目和评分结果列表
        QuestionAndResultListDTO questionAndResult = dataTreating.getQuestionAndResult(choices, app);
        Question question = questionAndResult.getQuestion();
        List<ScoringResult> scoringResultList = questionAndResult.getScoringResultList();
        // 2. 统计用户每个选择对应的属性个数，如 I = 10 个，E = 5 个
        // 初始化一个Map，用于存储每个选项的计数
        Map<String, Integer> optionCount = new HashMap<>();
        List<QuestionContentDTO> questionContent = JSONUtil.toList(question.getQuestionContent(), QuestionContentDTO.class);

        // 判断用户答案数量和题目是否一致
        if (questionContent.size() != choices.size()) {
            throw new WarnException(ErrorCode.PARAMS_ERROR);
        }

        // 建立题目选项序号和选项的映射关系
        Map<Integer, Map<String, String>> questionOptionMap = new HashMap<>();
        for (QuestionContentDTO content : questionContent) {
            Map<String, String> optionMap = new HashMap<>();
            for (QuestionContentDTO.Option option : content.getOptions()) {
                optionMap.put(option.getKey(), option.getResult());
            }
            questionOptionMap.put(questionContent.indexOf(content), optionMap);
        }
        // 遍历用户答案，统计属性个数
        for (int i = 0; i < choices.size(); i++) {
            Map<String, String> optionMap = questionOptionMap.get(i);
            String answer = choices.get(i);
            if (optionMap.containsKey(answer)) {
                String result = optionMap.get(answer);
                optionCount.put(result, optionCount.getOrDefault(result, 0) + 1);
            }
        }

        // 3. 遍历每种评分结果，计算哪个结果的得分更高
        // 初始化最高分数和最高分数对应的评分结果
        int maxScore = 0;
        ScoringResult maxScoringResult = scoringResultList.get(0);

        // 遍历评分结果列表
        for (ScoringResult scoringResult : scoringResultList) {
            List<String> resultProp = JSONUtil.toList(scoringResult.getResultProp(), String.class);
            // 计算当前评分结果的分数，[I, E] => [10, 5] => 15
            int score = resultProp.stream()
                    .mapToInt(prop -> optionCount.getOrDefault(prop, 0))
                    .sum();

            // 如果分数高于当前最高分数，更新最高分数和最高分数对应的评分结果
            if (score > maxScore) {
                maxScore = score;
                maxScoringResult = scoringResult;
            }
        }

        // 4. 构造返回值，填充答案对象的属性
        UserAnswer userAnswer = new UserAnswer();
        userAnswer.setAppId(app.getId());
        userAnswer.setAppType(app.getAppType());
        userAnswer.setScoringStrategy(app.getScoringStrategy());
        userAnswer.setChoices(JSONUtil.toJsonStr(choices));
        userAnswer.setResultId(maxScoringResult.getId());
        userAnswer.setResultName(maxScoringResult.getResultName());
        userAnswer.setResultDesc(maxScoringResult.getResultDesc());
        userAnswer.setResultPicture(maxScoringResult.getResultPicture());
        userAnswer.setResultScore(0);
        return userAnswer;
    }
}
